import { _decorator, Collider2D, Component, Contact2DType, EPhysics2DDrawFlags, ERigidBody2DType, EventTouch, instantiate, Label, macro, Node, NodeEventType, ParticleSystem2D, PhysicsSystem2D, Prefab, RigidBody, RigidBody2D, Script, Sprite, SpriteFrame, Touch, UITransform, v2, v3, Vec3 } from 'cc';
import { StaticResources } from './utils/StaticResources';
const { ccclass, property } = _decorator;

@ccclass('Root')
export class Root extends Component {

    //emoji预制体
    @property(Prefab) emoji:Prefab
    //粒子预制体
    @property(Prefab) emojiParticle:Prefab
    //出框检测红线
    @property(Node) check:Node
    //开始游戏ui
    @property(Node) startMenu:Node
    //游戏结束ui
    @property(Node) endMenu:Node
    //重新开始ui
    @property(Node) stopMenu:Node
    //分数节点
    @property(Node) scoreNode:Node
    private canvas:Node

    //用于存储emoji的图片
    private emojis:SpriteFrame[]

    //用于存放游戏顶部的emoji
    private emojiNode:Node

    //用于存放所有的emoji节点
    private emojiNodes:Node[]

    //用于存放分数
    private score:number
    async start() {
        //加载所有的emoji图片
        this.emojis = await StaticResources.getAllEmoji()
        this.canvas = this.node.parent
    }
    //初始化所有的事件
    private initEvent()
    {
        this.canvas.on(NodeEventType.TOUCH_CANCEL,this.touchCancelHandle,this)
        this.canvas.on(NodeEventType.TOUCH_END,this.touchCancelHandle,this)
        this.canvas.on(NodeEventType.TOUCH_MOVE,this.touchMoveHandle,this)
        this.check.getComponent(Collider2D).on(Contact2DType.BEGIN_CONTACT,this.checkHandle,this)
    }
    //关闭所有事件
    private offEvent()
    {
        this.canvas.off(NodeEventType.TOUCH_CANCEL,this.touchCancelHandle,this)
        this.canvas.off(NodeEventType.TOUCH_END,this.touchCancelHandle,this)
        this.check.getComponent(Collider2D).off(Contact2DType.BEGIN_CONTACT,this.checkHandle,this)
        this.canvas.off(NodeEventType.TOUCH_MOVE,this.touchMoveHandle,this)
    }
    //移动事件回调函数
    private touchMoveHandle(e:EventTouch)
    {
        
        if(this.emojiNode)
        {
            this.moveEmoji(e)
        }
    }
    //取消点击事件回调函数
    private touchCancelHandle(e:EventTouch)
    {
        if(this.emojiNode)
        {
            this.emojiNode.getComponent(RigidBody2D).type = ERigidBody2DType.Dynamic
            this.emojiNode.getComponent(RigidBody2D).enabledContactListener = true
            this.emojiNode = null
            this.scheduleOnce(this.createEmoji,0.5)
        }
    }
    //检测有没有出界的emoji
    private checkHandle(selfCollider: Collider2D, otherCollider: Collider2D)
    {
        console.log('游戏结束')
        this.offEvent()
        //弹出结束界面
        this.endMenu.active = true
    }
    //控制emoji移动
    private moveEmoji(e:EventTouch)
    {
        const tag = this.emojiNode.getComponent(Collider2D).tag
        const contentSize = this.emojiNode.getComponent(UITransform).contentSize
        //计算emoji的半径
        const sizeR = this.emojiNode.scale.x * contentSize.x / 2
        const uiLocation = e.getUILocation()
        //确保emoji移动在框内
        if(uiLocation.x <  72 + sizeR)
        {
            this.emojiNode.setWorldPosition(72 + sizeR,this.emojiNode.worldPosition.y,0)
        }
        else if(uiLocation.x > 645 - sizeR)
        {
            this.emojiNode.setWorldPosition(645 - sizeR,this.emojiNode.worldPosition.y,0)
        }
        else
        {
            this.emojiNode.setWorldPosition(uiLocation.x,this.emojiNode.worldPosition.y,0)
        }
    }
    //创建emoji对象
    private createEmoji()
    {
        const randomIndex = Math.floor(Math.random() * 4);
        //初始化对象
        this.emojiNode = instantiate(this.emoji)
        this.node.getChildByName('emojis').addChild(this.emojiNode)
        this.emojiNode.getComponent(Collider2D).group = 8
        //设置刚体类型
        this.emojiNode.getComponent(RigidBody2D).type = ERigidBody2DType.Kinematic
        //根据缩印设置对应图像缩放和tag
        this.emojiNode.getComponent(Sprite).spriteFrame = this.emojis[randomIndex]
        this.emojiNode.setScale(v3(randomIndex + 2,randomIndex + 2,1))
        this.emojiNode.getComponent(Collider2D).tag = randomIndex + 1
        this.emojiNode.setPosition(v3(0,500,0))
    }
    //开始游戏
    startGame()
    {
        //初始化分数
        this.score = 0
        //隐藏ui界面
        this.startMenu.active = false
        this.stopMenu.active = false
        //初始化事件
        this.initEvent()
        //初始化顶部emoji
        if(!this.emojiNode)
        {
            this.createEmoji()
        }
    }
    //游戏结算
    private endGame()
    {
        //销毁顶部emoji
        if(this.emojiNode)
        {
            this.emojiNode.destroy()
            this.emojiNode = null
        }
        //弹出ui层
        this.endMenu.active = false
        //获取所有的emoji节点
        this.emojiNodes = this.node.getChildByName('emojis').children
        //停止所有emoji的碰撞回调
        for(let i = 0;i<this.emojiNodes.length;i++)
        {
            this.emojiNodes[i].getComponent(RigidBody2D).enabledContactListener = false;
        }
        //开始逐个销毁emoji节点并统计分数
        this.schedule(this.endDestory,0.1)
    }
    //销毁emoji节点并统计分数
    private endDestory()
    {
        //如果所有emoji节点则停止计时器并弹出结算界面
        if(this.emojiNodes.length === 0)
        {
            this.unschedule(this.endDestory)
            this.scoreNode.getComponent(Label).string = `分数：${this.score}`
            this.stopMenu.active = true
            return
        }
        //获取当前销毁的emoji节点
        const emoji = this.emojiNodes[0]
        //获取tag值
        const tag = emoji.getComponent(Collider2D).tag
        //在被销毁emoji节点位置召唤粒子
        this.createParticle(v3(emoji.position.x,emoji.position.y,0),tag*100,tag*20,tag*40)
        //根据tag值加分
        this.score += 3**tag
        this.emojiNodes[0].destroy()
    }
    //创建粒子
    createParticle(position:Vec3,speed?:number,startSize?:number,endSize?:number)
    {
        const particle = instantiate(this.emojiParticle)
        this.node.addChild(particle)
        particle.setPosition(position)
        const particleConfig = particle.getComponent(ParticleSystem2D)
        particleConfig.speed = speed
        particleConfig.startSize = startSize
        particleConfig.endSize = endSize
    }
    update(deltaTime: number) {
        
    }
}


